-
-
Notifications
You must be signed in to change notification settings - Fork 272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CID-152200,CID-152202] - Resource leak in Cipher I/O streams on exceptional paths #104
[CID-152200,CID-152202] - Resource leak in Cipher I/O streams on exceptional paths #104
Conversation
oleg-nenashev
commented
Aug 20, 2016
•
edited
Loading
edited
- https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836377&defectInstanceId=4427377&mergedDefectId=152202
- https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836377&defectInstanceId=4427377&mergedDefectId=152200
@reviewbybees @jenkinsci/code-reviewers |
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
EngineUtil.closeAndLogFailures(in, LOGGER, "CipherInputStream", socket.toString()); | ||
EngineUtil.closeAndLogFailures(out, LOGGER, "CipherOutputStream", socket.toString()); | ||
if (ex instanceof RuntimeException) { | ||
throw (IOException) ex; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cast seems unsafe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unsafe... I've messed up something
@olivergondza fixed |
} catch (Exception ex) { | ||
// Something went wrong. We want to gracefully close Cipher stream in the case they were open | ||
EngineUtil.closeAndLogFailures(in, LOGGER, "CipherInputStream", socket.toString()); | ||
EngineUtil.closeAndLogFailures(out, LOGGER, "CipherOutputStream", socket.toString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐜 better (under Java 7) to use Throwable.addSuppressed
. Or simpler still:
Channel channel = null;
CipherInputStream in = new CipherInputStream(SocketChannelStream.in(socket), channelCiphers.getDecryptCipher());
try {
CipherOutputStream out = new CipherOutputStream(SocketChannelStream.out(socket), channelCiphers.getEncryptCipher());
try {
return channel = createChannelBuilder(nodeName).build(in, out);
} finally {
if (channel == null) {
out.close();
}
}
} finally {
if (channel == null) {
in.close();
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even better would be a utility (should I file a suggestion for Guava?):
public static class ClosePartials implements AutoCloseable {
private final List<AutoCloseable> things = new ArrayList<>();
public ClosePartials() {}
public <T extends AutoCloseable> T with(T thing) {
things.add(thing);
return thing;
}
/** @param <T> recommended to also be {@link AutoCloseable} */
public <T> T done(T thing) {
things.clear();
return thing;
}
@Override
public void close() throws Exception {
Exception x = null;
for (AutoCloseable thing : things) {
try {
thing.close();
} catch (Throwable t) {
if (x == null) {
if (t instanceof Exception) {
x = (Exception) t;
} else {
x = new Exception(t);
}
} else {
x.addSuppressed(t);
}
}
}
if (x != null) {
throw x;
}
}
}
Example usage:
public static Channel example(Socket s, Cipher c, ChannelBuilder cb) throws Exception {
try (ClosePartials cp = new ClosePartials();
InputStream sin = cp.with(SocketChannelStream.in(s));
CipherInputStream cin = cp.with(new CipherInputStream(sin, c));
OutputStream sout = cp.with(SocketChannelStream.out(s));
CipherOutputStream cout = cp.with(new CipherOutputStream(sout, c))) {
return cp.done(cb.build(cin, cout));
}
}
In general, methods which deliberately create closeable [sic] objects but then conceal them as references inside some higher-level closeable object are risky, because even if the ultimate caller is careful to close
the final object, its close
method might not be foolproof. Channel.close
does not even pretend to guarantee that all streams it was originally passed will be closed by the time the method completes.
Anyway, 🐝 as it stands. |
All these PRs go against stable-2.x, which will stay on Java6 |
@reviewbybees done |
* [maven-release-plugin] prepare release remoting-2.62 * [maven-release-plugin] prepare for next development iteration * [FIXED JENKINS-37539] - Prevent NPE in Engine#connect() when host or port are null or empty (#101) Bug diagnosis: * https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836372&defectInstanceId=4427367&mergedDefectId=152195 * https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836372&defectInstanceId=4427365&mergedDefectId=152194 * [CID-152201] - Fix resource leak in remoting.jnlp.Main (#102) * [CID-152200,CID-152202] - Resource leak in Cipher I/O streams on exceptional paths (#104) * [CID-152200,CID-152202] - Resource leak in Cipher I/O streams on exceptional paths * https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836377&defectInstanceId=4427377&mergedDefectId=152202 * https://scan8.coverity.com/reports.htm#v14462/p10499/fileInstanceId=12836377&defectInstanceId=4427377&mergedDefectId=152200 * [CID-152202] - Fix typo noticed by @olivergondza * Fix another merge conflict * Remove EngineUtil#closeAndLogFailures()
2.61 does not exist, there was an issue during the release Changes in 2.62: https://github.com/jenkinsci/remoting/blob/stable-2.x/CHANGELOG.md#2622 * [JENKINS-38539](https://issues.jenkins-ci.org/browse/JENKINS-38539) - Stability: Turn on SO_KEEPALIVE and provide CLI option to turn it off again. (jenkinsci/remoting#110) * [JENKINS-37539](https://issues.jenkins-ci.org/browse/JENKINS-37539) - Prevent <code>NullPointerException</code> in <code>Engine#connect()</code> when host or port parameters are <code>null</code> or empty. (jenkinsci/remoting#101) * [CID-152201] - Fix resource leak in <code>remoting.jnlp.Main</code>. (jenkinsci/remoting#102) * [CID-152200,CID-152202] - Resource leak in Encryption Cipher I/O streams on exceptional paths. (jenkinsci/remoting#104)
…2585) 2.61 does not exist, there was an issue during the release Changes in 2.62: https://github.com/jenkinsci/remoting/blob/stable-2.x/CHANGELOG.md#2622 * [JENKINS-38539](https://issues.jenkins-ci.org/browse/JENKINS-38539) - Stability: Turn on SO_KEEPALIVE and provide CLI option to turn it off again. (jenkinsci/remoting#110) * [JENKINS-37539](https://issues.jenkins-ci.org/browse/JENKINS-37539) - Prevent <code>NullPointerException</code> in <code>Engine#connect()</code> when host or port parameters are <code>null</code> or empty. (jenkinsci/remoting#101) * [CID-152201] - Fix resource leak in <code>remoting.jnlp.Main</code>. (jenkinsci/remoting#102) * [CID-152200,CID-152202] - Resource leak in Encryption Cipher I/O streams on exceptional paths. (jenkinsci/remoting#104)
This PR picks the latest available version of remoting stable-2.x. All the fixes have been integrated into remoting-3.0 and soaked enough. * [JENKINS-38539](https://issues.jenkins-ci.org/browse/JENKINS-38539) - Stability: Turn on SO_KEEPALIVE by default and provide CLI option to turn it off again. (jenkinsci/remoting#110) * [JENKINS-37539](https://issues.jenkins-ci.org/browse/JENKINS-37539) - Prevent <code>NullPointerException</code> in <code>Engine#connect()</code> when host or port parameters are <code>null</code> or empty. (jenkinsci/remoting#101) * [CID-152201] - Fix resource leak in <code>remoting.jnlp.Main</code>. (jenkinsci/remoting#102) * [CID-152200,CID-152202] - Resource leak in Encryption Cipher I/O streams on exceptional paths. (jenkinsci/remoting#104)